package testadventure;


import edu.clemson.cs.hamptos.adventure.AdventureCommand;
import edu.clemson.cs.hamptos.adventure.AdventureEngine;
import edu.clemson.cs.hamptos.adventure.AdventureParser;
import edu.clemson.cs.hamptos.adventure.AdventureTarget;
import edu.clemson.cs.hamptos.adventure.NoSuchTargetException;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;

/**
 *<p>This class is an implementation of <code>AdventureParser</code>.
 * The user's input is translated into an <code>AdventureCommand</code>so that
 * the Player's inventory and location can be updated based on the input from
 * the user.</p>
 * @author Umbrella Corp.
 */
public class Parser implements AdventureParser {
    /**
     * <p>Initializes a newly created <code>Parser</code> object.</p>
     */
    Parser()
    {
        String artString = null;
        String prepString = null;
        try {
            artString = TheAdventure.ripStringFromFile
                       (new File("./ScriptArticles.txt"));
            prepString = TheAdventure.ripStringFromFile
                         (new File("./ScriptPrepositions.txt"));
        } catch (FileNotFoundException ex) {
            System.err.println("Could not initialize the preps and articles," 
                    + " check to make sure they are there");
            System.err.println("Error thrown: " + ex.getMessage());
        }
        StringTokenizer artTokens = new StringTokenizer(artString);
        while (artTokens.hasMoreTokens()) {       //create an array list of  
            articleList.add(artTokens.nextToken());//articles and prepositions
        }
        StringTokenizer prepTokens = new StringTokenizer(prepString);
        while (prepTokens.hasMoreTokens()) {       //create an array list of  
            prepList.add(prepTokens.nextToken());//articles and prepositions
        }
    }
    ArrayList<String> articleList = new ArrayList<String>();
    ArrayList<String> prepList = new ArrayList<String>();
    /**
     * <p>This method receives a command retrieved by the user, removes the 
     * articles, (a,an,the), and returns an <code>AdventureCommand</code></p>.
     * @param command - of type <code>String</code>
     * @param e - an <code>AdventureEngine</code>
     * @return An <code>AdventureCommand</code>.
     * @throws NoSuchTargetException 
     */
    @Override
    public AdventureCommand parse(String command, AdventureEngine e) 
                                      throws NoSuchTargetException {
        String verb = null;
        String directobject = null;
        String indirectobject = null;

        //read input from the user
        StringTokenizer tokenizer = new StringTokenizer(command);
        String checkString = null;
        
        if (tokenizer.countTokens() == 0)
        {
            throw new IllegalArgumentException(command);
        }
        
        int pass = 0;
        int caseType = 0;
        try
        {
            while (tokenizer.hasMoreTokens()) {
                checkString = tokenizer.nextToken();

                //gets Verb first
                if (pass == 0)
                {
                    verb = checkString;
                    pass++;
                }
                else if (pass == 1)
                {
                    //Verb - IO only case
                    if (prepList.contains(checkString))
                    {
                        checkString = tokenizer.nextToken();
                        if (articleList.contains(checkString))
                        {
                            checkString = tokenizer.nextToken();
                        }
                        indirectobject = checkString;
                        pass++;
                        caseType = 3;
                    }
                    //Verb - DO - ? case
                    else
                    {
                        if (articleList.contains(checkString))
                        {
                            checkString = tokenizer.nextToken();
                        }
                        directobject = checkString;
                        pass++;
                        caseType = 1;
                    }
                }
                else if (pass == 2)
                {
                    //Verb - DO - IO case
                    if (prepList.contains(checkString))
                    {
                        checkString = tokenizer.nextToken();
                        if (articleList.contains(checkString))
                        {
                            checkString = tokenizer.nextToken();
                        }
                        indirectobject = checkString;
                        pass++;
                        caseType = 2;
                    }
                    else
                    {
                        throw new IllegalArgumentException();
                    }
                }
                else
                {
                    throw new IllegalArgumentException();
                }
            }
        }
        catch (NoSuchElementException ex)
        {
            throw new IllegalArgumentException();
        }

        AdventureTarget directobjectTarget = null;
        AdventureTarget indirectobjectTarget = null;
        if (directobject != null)
        {
            try
            {
                directobjectTarget = e.playerInventoryContains(directobject);
            }
            catch(NoSuchTargetException ex)
            {
                try
                {
                    directobjectTarget = e.getPlayerLocation().
                                         containsLocalTarget(directobject);
                }
                catch(NoSuchTargetException exNone)
                {
                    throw new NoSuchTargetException(exNone.getItemName());
                }
            }
        }
        if (indirectobject != null)
        {
            try
            {
                indirectobjectTarget = e.playerInventoryContains(indirectobject);
            }
            catch(NoSuchTargetException ex)
            {
                try
                {
                    indirectobjectTarget = e.getPlayerLocation().
                                           containsLocalTarget(indirectobject);
                }
                catch(NoSuchTargetException exNone)
                {
                    throw new NoSuchTargetException(exNone.getItemName());
                }
            }
        }

        //creates a new AdventureCommand to be returned
        AdventureCommand comm;
        if (caseType == 0)
        {
            //just a verb
            comm = new AdventureCommand(verb);
        }
        else if (caseType == 1)
        {
            //verb do

            comm = new AdventureCommand(verb,
                        directobjectTarget,directobject);
        }
        else if ((caseType == 2) || (caseType == 3))
        {
            //verb do io
            comm = new AdventureCommand(verb,
                    directobjectTarget, directobject, 
                    indirectobjectTarget, indirectobject);
        }
        else 
        {
            throw new IllegalArgumentException(command);
        }

        return comm; 
    }
}
